/*
 * @Author: 0x9DEFA478
 * @Date: 2022-01-22 21:18:46
 * @LastEditTime: 2022-02-25 00:20:58
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "../Console/H_NES_Console.h"




extern int H_NES_Mapper_Init(void* v,Huint16 MapperNumber);
extern void H_NES_Mapper_DeInit(void* v);




int H_NES_Cartridge_GetROM_Info(Hbyte* Header
  ,Huint32* PRG_ROM_Offset,Huint32* PRG_ROM_Size
  ,Huint32* CHR_ROM_Offset,Huint32* CHR_ROM_Size){
  Hbyte* Flag;


  Flag=Header;

  if((Flag[0]!='N')||(Flag[1]!='E')||(Flag[2]!='S')){
    return vH_NES_Result_ROMError;
  }

  if((Flag[7]&0x0CU)==0x04U){
    //NES2.0

    return vH_NES_Result_ROMError;
  }else{
    //iNES

    PRG_ROM_Size[0]=0x4000U*Flag[4];
    CHR_ROM_Size[0]=0x2000U*Flag[5];
    if((Flag[6]&0x04U)==0U){
      PRG_ROM_Offset[0]=16U;
      CHR_ROM_Offset[0]=16U+PRG_ROM_Size[0];
    }else{
      PRG_ROM_Offset[0]=16U+512U;
      CHR_ROM_Offset[0]=16U+512U+PRG_ROM_Size[0];
    }

  }

  return vH_NES_Result_OK;
}

int H_NES_Cartridge_LoadROM_Scatter(H_NES_Console* Console,Hbyte* Header,Hbyte* PRG_ROM,Hbyte* CHR_ROM){
  Hbyte* Flag;
  Huint32 PRG_ROM_Size;
  Huint32 CHR_ROM_Size;
  Hint32 PRG_RAM_Size;
  Hbyte* CHR_RAM;
  Huint16 MapperNumber;
  int r;


  PRG_RAM_Size=0;
  CHR_RAM=NULL;

  Flag=Header;

  if((Flag[0]!='N')||(Flag[1]!='E')||(Flag[2]!='S')){
    return vH_NES_Result_ROMError;
  }

  if((Flag[7]&0x0CU)==0x04U){
    //NES2.0

    r=vH_NES_Result_ROMError;
    goto Error0;
  }else{
    //iNES

    MapperNumber=(Flag[6]>>4)|(Flag[7]>>4);

    if((Flag[6]&0x08U)==0U){
      if((Flag[6]&0x01U)==0U){
        //命名表垂直排列
        Console->PPU.NameTable[0]=&((Hbyte*)Console->PPU.VRAM)[0];
        Console->PPU.NameTable[1]=&((Hbyte*)Console->PPU.VRAM)[0];
        Console->PPU.NameTable[2]=&((Hbyte*)Console->PPU.VRAM)[0x400];
        Console->PPU.NameTable[3]=&((Hbyte*)Console->PPU.VRAM)[0x400];
        Console->PPU.VRAM_ScreenType=0x01U;
      }else{
        //命名表水平排列
        Console->PPU.NameTable[0]=&((Hbyte*)Console->PPU.VRAM)[0];
        Console->PPU.NameTable[1]=&((Hbyte*)Console->PPU.VRAM)[0x400];
        Console->PPU.NameTable[2]=&((Hbyte*)Console->PPU.VRAM)[0];
        Console->PPU.NameTable[3]=&((Hbyte*)Console->PPU.VRAM)[0x400];
        Console->PPU.VRAM_ScreenType=0x02U;
      }
    }else{
      //4块显存
      Console->PPU.NameTable[0]=&((Hbyte*)Console->PPU.VRAM)[0];
      Console->PPU.NameTable[1]=&((Hbyte*)Console->PPU.VRAM)[0x400];
      Console->PPU.NameTable[2]=&((Hbyte*)Console->PPU.VRAM)[0x800];
      Console->PPU.NameTable[3]=&((Hbyte*)Console->PPU.VRAM)[0xC00];
      Console->PPU.VRAM_ScreenType=0x03U;
    }
    


    PRG_ROM_Size=0x4000U*Flag[4];
    CHR_ROM_Size=0x2000U*Flag[5];
    if((Flag[6]&0x04U)==0U){
      PRG_ROM=&Flag[16];
      CHR_ROM=&Flag[16+PRG_ROM_Size];
    }else{
      PRG_ROM=&Flag[16+512];
      CHR_ROM=&Flag[16+512+PRG_ROM_Size];
    }

    //判断是否存在PRG_RAM
    if((Flag[6]&0x02U)!=0U){
      PRG_RAM_Size=-1;
    }

  }

  Console->Cartridge.Mapper.PRG_ROM=PRG_ROM;
  Console->Cartridge.Mapper.PRG_ROM_Size=PRG_ROM_Size;
  if(CHR_ROM_Size==0U){
    Console->Cartridge.Mapper.CHR_RAM_Size=0x2000;
    CHR_RAM=Console->Memory.Malloc(0x2000);
    if(CHR_RAM==NULL){
      r=vH_NES_Result_CHR_RAM_AllocFail;
      goto Error0;
    }
    Console->Cartridge.Mapper.CHR_ROM=CHR_RAM;
  }else{
    Console->Cartridge.Mapper.CHR_RAM_Size=0;
    Console->Cartridge.Mapper.CHR_ROM=CHR_ROM;
  }
  Console->Cartridge.Mapper.CHR_ROM_Size=CHR_ROM_Size;
  Console->Cartridge.Mapper.PRG_RAM=NULL;
  Console->Cartridge.Mapper.PRG_RAM_Size=PRG_RAM_Size;
  Console->Cartridge.Mapper.CHR_RAM=CHR_RAM;

  Console->Cartridge.Option.MMC3_A12_Rise=NULL;


  r=H_NES_Mapper_Init(Console,MapperNumber);
  if(r==vH_NES_Result_OK){
    return r;
  }


Error0:
  if(CHR_RAM!=NULL){
    Console->Memory.Free(CHR_RAM);
  }

  return r;
}

int H_NES_Cartridge_LoadROM(H_NES_Console* Console,void* NESROM){
  Huint32 PRG_ROM_Offset;
  Huint32 PRG_ROM_Size;
  Huint32 CHR_ROM_Offset;
  Huint32 CHR_ROM_Size;
  int r;


  r=H_NES_Cartridge_GetROM_Info(NESROM,&PRG_ROM_Offset,&PRG_ROM_Size,&CHR_ROM_Offset,&CHR_ROM_Size);
  if(r!=vH_NES_Result_OK){
    return r;
  }
  return H_NES_Cartridge_LoadROM_Scatter(Console,NESROM,&((Hbyte*)NESROM)[PRG_ROM_Offset],&((Hbyte*)NESROM)[CHR_ROM_Offset]);
}

void H_NES_Cartridge_UnloadROM(H_NES_Console* Console){
  void* p;

  H_NES_Mapper_DeInit(Console);

  p=Console->Cartridge.Mapper.CHR_RAM;
  if(p!=NULL){
    Console->Memory.Free(p);
  }
}



